import * as monaco from 'monaco-editor'
import { 
  getAutoCompleteSuggestions, 
  getSchemaInfo,
  TableInfo,
  ColumnInfo,
  AutoCompleteSuggestions 
} from '@/services/schemaAPI'

export class SchemaProvider {
  private connectionId: string | null = null
  private schemaCache: Map<string, any> = new Map()
  private disposables: monaco.IDisposable[] = []

  constructor() {
    this.registerCompletionProvider()
    this.registerHoverProvider()
    this.registerSignatureHelpProvider()
  }

  /**
   * 设置当前连接ID
   */
  setConnectionId(connectionId: string | null) {
    this.connectionId = connectionId
    this.clearCache()
  }

  /**
   * 清除缓存
   */
  clearCache() {
    this.schemaCache.clear()
  }

  /**
   * 注册自动补全提供器
   */
  private registerCompletionProvider() {
    const provider = monaco.languages.registerCompletionItemProvider('sql', {
      provideCompletionItems: async (model, position, context, token) => {
        if (!this.connectionId) {
          return { suggestions: [] }
        }

        try {
          // 获取当前单词和上下文
          const wordInfo = model.getWordUntilPosition(position)
          const currentWord = wordInfo.word
          
          // 获取前面的单词作为上下文
          const textUntilPosition = model.getValueInRange({
            startLineNumber: 1,
            startColumn: 1,
            endLineNumber: position.lineNumber,
            endColumn: position.column,
          })
          
          const previousWords = this.extractPreviousWords(textUntilPosition, currentWord)
          
          // 获取自动补全建议
          const response = await getAutoCompleteSuggestions(this.connectionId, {
            currentWord,
            previousWords,
            position: { line: position.lineNumber, column: position.column },
          })
          
          if (!response.success || !response.data) {
            return { suggestions: [] }
          }
          
          const suggestions = this.convertToMonacoSuggestions(
            response.data,
            wordInfo.startColumn,
            wordInfo.endColumn
          )
          
          return { suggestions }
        } catch (error) {
          console.error('Failed to get completion suggestions:', error)
          return { suggestions: [] }
        }
      },
      
      triggerCharacters: ['.', ' ', '(', ','],
    })
    
    this.disposables.push(provider)
  }

  /**
   * 注册悬停提示提供器
   */
  private registerHoverProvider() {
    const provider = monaco.languages.registerHoverProvider('sql', {
      provideHover: async (model, position) => {
        if (!this.connectionId) {
          return null
        }

        try {
          const word = model.getWordAtPosition(position)
          if (!word) {
            return null
          }

          // 尝试获取表或列的详细信息
          const hoverInfo = await this.getHoverInfo(word.word)
          if (!hoverInfo) {
            return null
          }

          return {
            range: new monaco.Range(
              position.lineNumber,
              word.startColumn,
              position.lineNumber,
              word.endColumn
            ),
            contents: [
              { value: hoverInfo.title },
              { value: hoverInfo.description },
            ],
          }
        } catch (error) {
          console.error('Failed to get hover info:', error)
          return null
        }
      },
    })
    
    this.disposables.push(provider)
  }

  /**
   * 注册签名帮助提供器
   */
  private registerSignatureHelpProvider() {
    const provider = monaco.languages.registerSignatureHelpProvider('sql', {
      signatureHelpTriggerCharacters: ['(', ','],
      provideSignatureHelp: async (model, position, token, context) => {
        // 获取函数名和参数信息
        const textUntilPosition = model.getValueInRange({
          startLineNumber: position.lineNumber,
          startColumn: 1,
          endLineNumber: position.lineNumber,
          endColumn: position.column,
        })
        
        const functionMatch = textUntilPosition.match(/(\w+)\s*\([^)]*$/i)
        if (!functionMatch) {
          return null
        }
        
        const functionName = functionMatch[1].toUpperCase()
        const signatureInfo = this.getFunctionSignature(functionName)
        
        if (!signatureInfo) {
          return null
        }
        
        return {
          value: {
            signatures: [
              {
                label: signatureInfo.signature,
                documentation: signatureInfo.description,
                parameters: signatureInfo.parameters.map(param => ({
                  label: param.name,
                  documentation: param.description,
                })),
              },
            ],
            activeSignature: 0,
            activeParameter: this.getActiveParameterIndex(textUntilPosition),
          },
          dispose: () => {},
        }
      },
    })
    
    this.disposables.push(provider)
  }

  /**
   * 提取前面的单词作为上下文
   */
  private extractPreviousWords(text: string, currentWord: string): string[] {
    // 移除当前单词
    const textWithoutCurrent = text.slice(0, text.length - currentWord.length)
    
    // 提取单词，忽略标点符号
    const words = textWithoutCurrent
      .replace(/[^\w\s]/g, ' ')
      .split(/\s+/)
      .filter(word => word.length > 0)
      .slice(-10) // 只取最近的10个单词
    
    return words
  }

  /**
   * 转换为Monaco编辑器的建议格式
   */
  private convertToMonacoSuggestions(
    suggestions: AutoCompleteSuggestions,
    startColumn: number,
    endColumn: number
  ): monaco.languages.CompletionItem[] {
    const items: monaco.languages.CompletionItem[] = []
    
    // 表名建议
    suggestions.tables.forEach(table => {
      items.push({
        label: table.table_name,
        kind: monaco.languages.CompletionItemKind.Class,
        insertText: table.table_name,
        detail: `Table: ${table.table_schema}.${table.table_name}`,
        documentation: table.table_comment || 'Database table',
        range: {
          startLineNumber: 0,
          startColumn,
          endLineNumber: 0,
          endColumn,
        },
        sortText: `1_${table.table_name}`, // 表名优先级较高
      })
    })
    
    // 列名建议
    suggestions.columns.forEach(column => {
      items.push({
        label: column.column_name,
        kind: monaco.languages.CompletionItemKind.Field,
        insertText: column.column_name,
        detail: `Column: ${column.data_type}${column.is_nullable ? ' (nullable)' : ''}`,
        documentation: column.column_comment || `Column of type ${column.data_type}`,
        range: {
          startLineNumber: 0,
          startColumn,
          endLineNumber: 0,
          endColumn,
        },
        sortText: `2_${column.column_name}`, // 列名优先级中等
      })
    })
    
    // 关键字建议
    suggestions.keywords.forEach(keyword => {
      items.push({
        label: keyword,
        kind: monaco.languages.CompletionItemKind.Keyword,
        insertText: keyword,
        detail: 'SQL Keyword',
        range: {
          startLineNumber: 0,
          startColumn,
          endLineNumber: 0,
          endColumn,
        },
        sortText: `3_${keyword}`, // 关键字优先级较低
      })
    })
    
    // 函数建议
    suggestions.functions.forEach(func => {
      const signature = this.getFunctionSignature(func)
      items.push({
        label: func,
        kind: monaco.languages.CompletionItemKind.Function,
        insertText: signature ? `${func}($1)` : func,
        insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
        detail: 'SQL Function',
        documentation: signature?.description || 'SQL function',
        range: {
          startLineNumber: 0,
          startColumn,
          endLineNumber: 0,
          endColumn,
        },
        sortText: `4_${func}`, // 函数优先级最低
      })
    })
    
    return items
  }

  /**
   * 获取悬停信息
   */
  private async getHoverInfo(word: string): Promise<{title: string, description: string} | null> {
    if (!this.connectionId) {
      return null
    }

    try {
      // 尝试从缓存获取schema信息
      let schemaInfo = this.schemaCache.get(this.connectionId)
      if (!schemaInfo) {
        const response = await getSchemaInfo(this.connectionId)
        if (response.success && response.data) {
          schemaInfo = response.data
          this.schemaCache.set(this.connectionId, schemaInfo)
        } else {
          return null
        }
      }

      // 检查是否是表名
      const table = schemaInfo.tables.find((t: TableInfo) => 
        t.table_name.toLowerCase() === word.toLowerCase()
      )
      if (table) {
        return {
          title: `**Table:** ${table.table_schema}.${table.table_name}`,
          description: table.table_comment || 'Database table',
        }
      }

      // 检查是否是列名
      for (const tableName of Object.keys(schemaInfo.columns)) {
        const column = schemaInfo.columns[tableName].find((c: ColumnInfo) =>
          c.column_name.toLowerCase() === word.toLowerCase()
        )
        if (column) {
          return {
            title: `**Column:** ${column.column_name}`,
            description: `Type: ${column.data_type}${column.is_nullable ? ' (nullable)' : ''}\n${column.column_comment || ''}`,
          }
        }
      }

      // 检查是否是函数
      const func = schemaInfo.functions.find((f: string) =>
        f.toLowerCase() === word.toLowerCase()
      )
      if (func) {
        const signature = this.getFunctionSignature(func)
        return {
          title: `**Function:** ${func}`,
          description: signature?.description || 'SQL function',
        }
      }

      return null
    } catch (error) {
      console.error('Failed to get hover info:', error)
      return null
    }
  }

  /**
   * 获取函数签名信息
   */
  private getFunctionSignature(functionName: string): {
    signature: string
    description: string
    parameters: { name: string, description: string }[]
  } | null {
    const signatures: { [key: string]: any } = {
      'COUNT': {
        signature: 'COUNT(expression)',
        description: 'Returns the number of rows that match a specified criterion',
        parameters: [
          { name: 'expression', description: 'The column or expression to count' }
        ],
      },
      'SUM': {
        signature: 'SUM(expression)',
        description: 'Returns the sum of a numeric column',
        parameters: [
          { name: 'expression', description: 'The numeric column or expression to sum' }
        ],
      },
      'AVG': {
        signature: 'AVG(expression)',
        description: 'Returns the average value of a numeric column',
        parameters: [
          { name: 'expression', description: 'The numeric column or expression to average' }
        ],
      },
      'MAX': {
        signature: 'MAX(expression)',
        description: 'Returns the maximum value in a set of values',
        parameters: [
          { name: 'expression', description: 'The column or expression to find maximum' }
        ],
      },
      'MIN': {
        signature: 'MIN(expression)',
        description: 'Returns the minimum value in a set of values',
        parameters: [
          { name: 'expression', description: 'The column or expression to find minimum' }
        ],
      },
      'CONCAT': {
        signature: 'CONCAT(string1, string2, ...)',
        description: 'Concatenates two or more strings',
        parameters: [
          { name: 'string1', description: 'First string to concatenate' },
          { name: 'string2', description: 'Second string to concatenate' },
        ],
      },
      'SUBSTRING': {
        signature: 'SUBSTRING(string, start, length)',
        description: 'Extracts a substring from a string',
        parameters: [
          { name: 'string', description: 'The source string' },
          { name: 'start', description: 'Starting position (1-based)' },
          { name: 'length', description: 'Length of substring to extract' },
        ],
      },
      'DATE_FORMAT': {
        signature: 'DATE_FORMAT(date, format)',
        description: 'Formats a date according to the specified format',
        parameters: [
          { name: 'date', description: 'The date to format' },
          { name: 'format', description: 'The format string' },
        ],
      },
    }
    
    return signatures[functionName.toUpperCase()] || null
  }

  /**
   * 获取当前活跃的参数索引
   */
  private getActiveParameterIndex(text: string): number {
    const commaCount = (text.match(/,/g) || []).length
    return commaCount
  }

  /**
   * 销毁提供器
   */
  dispose() {
    this.disposables.forEach(disposable => disposable.dispose())
    this.disposables = []
    this.clearCache()
  }
}

// 创建全局实例
export const schemaProvider = new SchemaProvider()